/****************************************************************************************/
/*                                                                     					*/
/*  M16C/62P Group Program Collection                                  					*/
/*                                                                     					*/
/*  FILE NAME : serial.c                           		            					*/
/*  CPU       : This program is the Serial flash boot loader by Xmodem data transfer	*/
/*  HISTORY   : 2006.12.08 Ver 0.01                                    					*/
/*                                                                    	 				*/
/*  Copyright (C) 2006. Renesas Technology Corp.                       					*/
/*  Copyright (C) 2006. Renesas Solutions Corp.                        					*/
/*  All right reserved.                                                					*/
/*                                                                     					*/
/*****************************************************************************************/

/**************************************/
/*    include file                    */
/**************************************/
#include <string.h>
#include "delay_timer.h"
#include "serial.h"

#include "sfr62p.h"

/**************************************/
/*   External reference declaration   */
/**************************************/
extern volatile unsigned char TimerChannelDelayStatus[];

/****************************************/
/*    InitSci function                  */
/****************************************/
void InitSci ( void )
{
	volatile unsigned long bit_delay;
	
	// serial port initialisation
	//
			
	// transmit/receive mode register
	smd0_u0mr = 1;				//	SMD2	SMD1	SMD0

	smd1_u0mr = 0;				//	0		0		0		- serial I/O disabled
								//	0		0		0		- serial I/O disabled

	smd2_u0mr = 1;				//	0		0		1		- clock synchronouse serial I/O mode
								//	0		0		1		- clock synchronouse serial I/O mode


								//	0		1		0		- I2C mode
								//	0		1		1		- DO NOT SET
								//	1		0		0		- UART mode transfer data 7 bits long	
								//	1		0		1		- UART mode transfer data 8 bits long
								//	1		1		0		- UART mode transfer data 9 bits long
								//	1		1		1		- DO NOT SET
	
								//	internal/external clock select bit
	ckdir_u0mr = 0;				//	0 - internal clock
								//	0 - internal clock
								//	1 - external clock (set port bit to input)
	
								// 	stop bit length select bit
	stps_u0mr = 0;				//	0 - one stop bit
								//	0 - one stop bit
								//	1 - two stop bits
								
								//	odd/even priority select bit
	pry_u0mr = 0;				//	0 - odd parity (active when PRYE = 1)
								//	0 - odd parity (active when PRYE = 1)
								//	1 - even parity (active when PRYE = 1)
								
								//	priority enable bit
	prye_u0mr = 0;				//	0 - parity disabled
								//	0 - parity disabled
								//	1 - parity enabled
								
								//	TxD/RxD I/O polarity reverse bit
	iopol_u0mr = 0;				//	0 - no reveers
								//	0 - no reveers
								//	1 - reverse

	// transmit/receive control register
								//	BRG count source select

	clk0_u0c0 = 0;				//	CLK1	CLK0

	clk1_u0c0 = 0;				//	0		0				- f1SIO or f2SIO selected
								//	CLK1	CLK0
								//	0		1				- f8SIO selected
								//	1		0				- f32SIO selected
								//	1		1				- DO NOT SET
				
								//	CTS/RTS function select bit
	crs_u0c0 = 0;				//	0 - CTS function selected
								//	0 - CTS function selected

								//	1 - RTS function selected
								//	CTS/RTS disable bit
	crd_u0c0 = 0;				//	0 - CTS/RTS function enabled
								//	0 - CTS function selected
								//	1 - CTS/RTS function disabled
								
								//	data output select bit
	nch_u0c0 = 0;				//	0 - TxD/SDA and SCL pins CMOS ouput
								//	0 - TxD/SDA and SCL pins CMOS ouput
								//	1 - TxD/SDA and SCL pins N-channel open drain outputs
								
								//	CLK polarity select bit
	ckpol_u0c0 = 0;				//	0 - Tx data output on falling edge of transfer clock and Rx data receive on rising edge
								//	0 - Tx data output on falling edge of transfer clock and Rx data receive on rising edge
								//	1 - Tx data output on rising edge of transfer clock and Rx data receive on falling edge
								
								//	transfer format select bit
	uform_u0c0 = 0;				//	0 - LSB first
								//	0 - LSB first
								//	1 - MSB first
	
	u0brg = BAUD(115200L);		// set baud rate
	
	// special mode register
	u0smr = 0;					//	not used in UART mode
	
	// special mode register 2
	u0smr2 = 0;					//	not used in UART mode
	
	// special mode register 3
	u0smr3 = 0;					//	not used in UART mode
	
	// special mode register 4
	u0smr4 = 0;					//	not used in UART mode
	
	//	transmit/receive control register

								// 	transmit enable bit
	te_u0c1 = 1;				//	0 - transmission disabled
								//	1 - transmission enabled
	
								// 	receive enable bit
	re_u0c1 = 1;				//	0 - reception disabled
	
								//	1 - reception enabled
	
	// make P6.3 an output
	pd6_3 = 1;
}

#pragma SECTION program ram_based_prg

/****************************************/
/*    ClearSCITxFlag function           */
/****************************************/
static void ClearSCITxFlag( void )
{
		// cleared by writing to the U0TB lower byte
}

/****************************************/
/*    RxByteWaiting function			*/
/****************************************/
static unsigned char RxByteWaiting ( void )
{
	//
	// returns 1 - if the byte is waiting
	// returns 0 - if no byte is waiting
	//
	
	unsigned char tmp;
	
	if( ri_u0c1 == 0 )
	{
		tmp = 0;
	}
	else
	{
		tmp = 1;
	}

	return tmp;
}

/****************************************/
/*    TxByteEmpty function				*/
/****************************************/
static unsigned char TxByteEmpty ( void )
{
	//
	// returns 1 - if the transmit register is empty
	// returns 0 - if the transmit register is not empty
	//
	
	unsigned char tmp;
	
	if( ti_u0c1 == 0 )
	{
		tmp = 0;
	}
	else
	{
		tmp = 1;
	}
	
	return tmp;
}

/****************************************/
/*    TxByteLoad function				*/
/****************************************/
static void TxByteLoad( unsigned char b )
{
		u0tbl = b;
}

/****************************************/
/*    SendByte function	    			*/
/****************************************/
void SendByte ( unsigned char b )
{
	while( TxByteEmpty() == 0 );
	TxByteLoad( b );
	ClearSCITxFlag();
}

/****************************************/
/*    SendString function   			*/
/****************************************/
void SendString ( char far *str )
{
	// sends string until NUL terminator is reached
	
	unsigned short us;

	us = 0;
	while ( str[us] != 0 )
	{
		SendByte ( (unsigned char) str[us] );
		us++;
	}
}

/****************************************/
/*    GetByte function       			*/
/****************************************/
unsigned short GetByte ( unsigned long timeout )
{
	//	timeout = time in ms for which to timeout the data reception
	//
	//	returns a 16-bit value
	//	upper (msb) byte contains status info
	//	lower (lsb) byte contains the data received from the SCI channel
	//
	//	status:
	//	OK
	//	ERROR
	//	TIMEOUT
	//
	
	union union_c2s c2s;	
	unsigned long tick_count;
	
	tick_count = timeout / MS_PER_TIMER_COMPARE_MATCH;
	
	StartDelayTimer();
	
	// wait for a byte to arrive
	while ( ( RxByteWaiting() == 0 ) && (tick_count) )
	{
		if ( GetDelayTimerStatus() )
		{
			StopDelayTimer();
			if ( --tick_count )
			{
				StartDelayTimer();
			}
		}
	}
	
	if ( RxByteWaiting() == 1 )
	{

	// read error flags and data
		c2s.us = u0rb;
		
		// check for errors
		if( c2s.uc[1] & 0x80 )
		{
			// Rx error
			//
			// check for parity error
			if( c2s.uc[1] & 0x40 )
			{
				// parity error
			}
			// check for framing error
			if( c2s.uc[1] & 0x20 )
			{
				// framing error
			}
			// check for overrun error
			if( c2s.uc[1] & 0x10 )
			{
				// overrun error
				// clearing the overrun error flag is a special case
				//
				// clear Tx enable

				re_u0c1 = 0;
				// set Tx enable

				re_u0c1 = 1;
			}
			
			c2s.uc[ 0 ] = ERROR;
		}
		else
		{
			// no Rx error
			c2s.uc[ 1 ] = c2s.uc[ 0 ];
			c2s.uc[ 0 ] = OK;
		}		
	}
	else
	{
		c2s.uc[0] = TIMEOUT;
	}
	
	return (c2s.us);
}

/****************************************/
/*    PurgeComms function       		*/
/****************************************/
void PurgeComms ( unsigned long timeout )
{
	union union_c2s c2s;
	
	do {
		c2s.us = GetByte( timeout );
	} while( (c2s.uc[0] != TIMEOUT) && (c2s.uc[0] != ERROR) );

}
